using System;
using System.Collections.Generic;
using System.Text;
using Xeml.Document.Contracts;
using Mpi.Common.Collections;

namespace Xeml.Document
{
    public class XemlCoreValidator : IValidator
    {
        #region IValidator Members


        protected virtual void OnValidation(SeverityCode sc, string msg, object relObject)
        {
            ValidationMessage vm = new ValidationMessage(sc, msg, relObject, false);
            if (Validation != null)
                Validation(this, vm);
        }

        public event EventHandler<ValidationMessage> Validation;


        private IDocument currentDoc;
        public void Validate(IDocument xemlDoc)
        {
            currentDoc = xemlDoc;
            ValidateStoryCount(SeverityCode.Error);
            ValidateParameterCount(SeverityCode.Error);
            ValidateSplitValueLink(SeverityCode.Error);
            ValidateValueCount(SeverityCode.Error);

        }

        public IXemlComponent Copy()
        {
            return new XemlCoreValidator();
        }

        #endregion

        private void ValidateStoryCount(SeverityCode sc)
        {
            if (currentDoc.StoryBoard.Count == 0)
                OnValidation(sc, "At least one story should be defined.", currentDoc.StoryBoard);
        }

        private void ValidateParameterCount(SeverityCode sc)
        {
            foreach (TreeNode<StoryBase> sbNode in currentDoc.StoryBoard)
            {
                if (sbNode.Content.Variables.Count == 0)
                    OnValidation(sc, "A story should define at least one variable.", sbNode.Content);
            }
        }

        private void ValidateSplitValueLink(SeverityCode sc)
        {
            //foreach (TreeNode<StoryBase> sbNode in currentDoc.StoryBoard)
            //{
            //    TimeSpan tsLink = TimeSpan.Zero;;
            //    if (sbNode.Content is Story)
            //        tsLink = TimeSpan.Zero;
            //    else if (sbNode.Content is StorySplit)
            //        tsLink = (sbNode.Content as StorySplit).Time;


            //    foreach (Parameter par in sbNode.Content.Parameters)
            //    {
            //        foreach (Property prop in par.Properties)
            //        {
            //            if (prop.Values.Count > 0)
            //            {
            //                if (prop.Values[0].Time != tsLink)
            //                {
            //                    if(tsLink == TimeSpan.Zero)
            //                        OnValidation(sc, "The first value in a story should be at timepoint zero.", prop.Values[0]);
            //                    else
            //                        OnValidation(sc, "The first value after splitting should be at the same timepoint as the splitting.", prop.Values[0]);
            //                }
            //            }
            //        }
            //    }

            //}
        }

        private void ValidateValueCount(SeverityCode sc)
        {
            foreach (TreeNode<StoryBase> sbNode in currentDoc.StoryBoard)
            {
                foreach (DynamicTerm par in sbNode.Content.Variables)
                {
                    if (par.Values.Count == 0)
                    {
                        OnValidation(sc, "A variable should define at least on value.", par);
                    }

                    foreach (ValueBase vb in par.Values)
                    {
                        if (vb is Cycle)
                        {
                            Cycle c = vb as Cycle;
                            if (c.Values.Count < 1)
                                OnValidation(sc, "A cycle should define at least one values.", c);
                        }
                    }
                    //foreach (Property prop in par.Properties)
                    //{
                    //    if (prop.Values.Count == 0)
                    //    {
                    //        OnValidation(sc, "A parameter/property should define at least on value.", prop);
                    //    }
                    //    else
                    //    {
                    //        foreach (ValueBase vb in prop.Values)
                    //        {
                    //            if (vb is Cycle)
                    //            {
                    //                Cycle c = vb as Cycle;
                    //                if (c.Values.Length < 2)
                    //                    OnValidation(sc, "A cycle should define at least two values.", c);
                    //            }
                    //        }
                    //    }

                    //}
                }
            }
        }

        #region IXemlComponent Members

        const string uri = "http://www.mpimp-golm.mpg.de/2007/XEML/CoreValidator";

        public string Uri
        {
            get { return uri; }
        }

        public Guid ComponentId
        {
            //nevr cahnge this entry
            get { return new Guid("{8C5F5B5F-EC22-4ba9-B9D7-C6B2F93F548A}"); }
        }

        public string Publisher
        {
            get { return "Max Planck Institute of Molecular Plant Physiology, Potsdam/Golm, Germany"; }
        }

        private Version _version = new Version(1, 0, 0, 0);
        public Version Version
        {
            get { return _version; }
        }

        public string ComponentName
        {
            get { return "XemlCoreValidator"; }
        }

        public string Author
        {
            get { return "Jan Hannemann"; }
        }

        public string Description
        {
            get { return "Implemnt the semantic validation of an Xeml document."; }
        }

        #endregion

        #region IIdObject<string> Members

        //public IdentifiableObjectCollection<string, IValidator> _collection;
        //public IdentifiableObjectCollection<string, IValidator> Collection
        //{
        //    get
        //    {
        //        return _collection;
        //    }
        //    set
        //    {
        //        if (value != null)
        //        {
        //            if (_collection != null)
        //            {
        //                _collection.Remove(this);
        //                _collection = null;
        //            }
        //            return;
        //        }
        //        if (!value.Contains(this))
        //            throw new ArgumentException("This is not a member of the target collection");
        //        else
        //            _collection = value;
        //    }
        //}


        //public object CollectionObject
        //{
        //    get
        //    {
        //        return _collection;
        //    }
        //    set
        //    {
        //        _collection = (IdentifiableObjectCollection<string, IValidator>)value;
        //    }
        //}

        //public string ObjectIdentifiere
        //{
        //    get { return uri; }
        //}

        #endregion
    }
}
